﻿
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using TransitionEffects;

namespace SharpSoft.WPF.Controls
{
    using SharpSoft.WPF.Converters;
    /// <summary>
    /// 可以为其内容提供过渡效果
    /// </summary>
    [TemplatePart(Name = "BORDER", Type = typeof(Border))]
    public class TransitionEffectControl : ContentControl
    {
        static TransitionEffectControl()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(TransitionEffectControl), new FrameworkPropertyMetadata(typeof(TransitionEffectControl)));
        }

        public TransitionEffectControl()
        {
            storyboard = new Storyboard() { FillBehavior = FillBehavior.Stop };
            storyboard.Completed += Storyboard_Completed;
            animation = new DoubleAnimation() { From = 0, To = 1, Duration = TimeSpan.FromSeconds(1), };
            var durBinding = new Binding("AnimationDuration") { Source = this, Mode = BindingMode.OneWay, Converter = new TimeSpanToDurationConverter() };
            BindingOperations.SetBinding(animation, DoubleAnimation.DurationProperty, durBinding);
            storyboard.Children.Add(animation);
        }

        #region 实现
        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();
            border = (Border)this.GetTemplateChild("BORDER");
        }
        private void Storyboard_Completed(object sender, EventArgs e)
        {
            isAnimating = false;
            this.CurrentTransitionEffect = null;
            if (this.border != null)
            {//动画完成后清除过渡效果 
                this.border.IsEnabled = true;//启用可能被禁用的border
                this.border.Effect = null;

                border.Child.Visibility = Visibility.Visible;
            }
            this.OnAnimationCompleted();
        }

        #endregion

        #region 事件
        /// <summary>
        /// 在过渡动画完成后触发
        /// </summary>
        public event RoutedEventHandler AnimationCompleted
        {
            add { AddHandler(AnimationCompletedEvent, value); }
            remove { RemoveHandler(AnimationCompletedEvent, value); }
        }

        public static readonly RoutedEvent AnimationCompletedEvent = EventManager.RegisterRoutedEvent(
        "AnimationCompleted", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(TransitionEffectControl));

        protected virtual void OnAnimationCompleted()
        {
            RoutedEventArgs args = new RoutedEventArgs();
            args.RoutedEvent = TransitionEffectControl.AnimationCompletedEvent;
            this.RaiseEvent(args);
        }

        #endregion

        #region 成员

        private Border border;
        private Brush snapshot = null;//当前快照
        private Storyboard storyboard;//处理过渡的动画
        private DoubleAnimation animation;
        private bool isAnimating = false;
        #endregion

        #region 方法

        /// <summary>
        /// 快照当前内容
        /// </summary>
        public ImageBrush Snapshot()
        {
            var bmp = VisualHelper.Capture(this, CaptureType.BitmapCacheBrush);
            var brush = new ImageBrush(bmp);
            this.snapshot = brush;
            return brush;
        }

        /// <summary>
        /// 对当前画面进行快照并开始过渡动画
        /// </summary>
        public void SnapshotAndStart()
        {
            if (border != null)
            {
                border.Child.Visibility = Visibility.Visible;
                Snapshot();
                BeginTransition(this.snapshot);
            }
        }
        /// <summary>
        /// 开始过渡出现
        /// </summary>
        public void Appear()
        {
            if (isAnimating)
            {
                return;
            }
            if (border != null)
            {
                border.Child.Visibility = Visibility.Visible;
                BeginTransition(new BitmapCacheBrush());
            }
        }
        /// <summary>
        /// 开始过度消失
        /// </summary>
        public void Disappear()
        {
            if (isAnimating)
            {
                return;
            }
            if (border != null)
            {
                Snapshot();
                border.Child.Visibility = Visibility.Hidden;
                BeginTransition(this.snapshot);
            }
        }
        /// <summary>
        /// 开始过渡
        /// </summary>
        /// <param name="old">旧画面</param>
        public void BeginTransition(Brush old)
        {
            if (isAnimating)
            {
                return;
            }
            if (border != null)
            {
                if (!EnabledInAnimating)
                {
                    this.border.IsEnabled = false;
                }
                var effect = createTransitionEffect(this.TransitionEffectType, this.Orientation);
                if (effect == null)
                {
                    return;
                }
                effect.OldImage = old;
                effect.Progress = 0d;
                border.Effect = effect;
                MessageQueueHepler.DoEvents();
                this.CurrentTransitionEffect = effect;

                Storyboard.SetTarget(this.animation, this.border);
                Storyboard.SetTargetProperty(this.animation, new PropertyPath("(0).(1)", Border.EffectProperty, TransitionEffect.ProgressProperty));
                this.storyboard.Begin(border, HandoffBehavior.Compose);
                isAnimating = true;
            }
        }

        /// <summary>
        /// 创建过渡效果的实例
        /// </summary>
        /// <returns></returns>
        private static TransitionEffect createTransitionEffect(TransitionEffectType effectType, Orientation orientation)
        {
            if (effectType == TransitionEffectType.None)
            {
                return null;
            }
            Type[] effects = new Type[] {
            typeof( BandedSwirlTransitionEffect ),
            typeof( BlindsTransitionEffect),
            typeof( BloodTransitionEffect),
            typeof( CircleRevealTransitionEffect),
            typeof( CircleStretchTransitionEffect),
            typeof( CircularBlurTransitionEffect),
            typeof( CloudRevealTransitionEffect),
            typeof( CrumbleTransitionEffect),
            typeof( DisolveTransitionEffect),
            typeof( DropFadeTransitionEffect),
            typeof( FadeTransitionEffect),
            typeof( LeastBrightTransitionEffect),
            typeof( LineRevealTransitionEffect),
            typeof( MostBrightTransitionEffect),
            typeof( PixelateInTransitionEffect),
            typeof( PixelateOutTransitionEffect),
            typeof( PixelateTransitionEffect),
            typeof( RadialBlurTransitionEffect),
            typeof( RadialWiggleTransitionEffect),
            typeof( RandomCircleRevealTransitionEffect),
            typeof( RippleTransitionEffect),
            typeof( RotateCrumbleTransitionEffect),
            typeof( SaturateTransitionEffect),
            typeof( ShrinkTransitionEffect),
            typeof( SlideInTransitionEffect),
            typeof( SlideOutTransitionEffect),
            typeof( SmoothSwirlGridTransitionEffect),
            typeof( SwirlGridTransitionEffect),
            typeof( SwirlTransitionEffect),
            typeof( WaterTransitionEffect),
            typeof( WaveTransitionEffect),
            };
            Type t;
            if (effectType == TransitionEffectType.Random)
            {
                var i = new Random().Next(0, effects.Length);
                t = effects[i];
            }
            else
            {
                t = effects[(int)effectType];
            }
            var effect = Activator.CreateInstance(t) as TransitionEffect;
            //下面为不同类型的过渡效果提供默认参数
            if (effect is SlideInTransitionEffect slideIn)
            {
                if (orientation == Orientation.Vertical)
                {
                    slideIn.SlideAmount = new Point(0, 1);
                }

            }
            else if (effect is SlideOutTransitionEffect slideOut)
            {
                if (orientation == Orientation.Vertical)
                {
                    slideOut.SlideAmount = new Point(0, 1);
                }
            }
            return effect;

        }

        #endregion

        #region 属性


        /// <summary>
        /// 设置过渡效果类型
        /// </summary>
        public TransitionEffectType TransitionEffectType
        {
            get { return (TransitionEffectType)GetValue(EffectTypeProperty); }
            set { SetValue(EffectTypeProperty, value); }
        }

        public static readonly DependencyProperty EffectTypeProperty =
            DependencyProperty.Register("TransitionEffectType", typeof(TransitionEffectType), typeof(TransitionEffectControl), new PropertyMetadata(TransitionEffectType.SlideOut));




        /// <summary>
        /// 获取当前正在进行的过渡效果(过渡未开始或已完成值为null)
        /// </summary>
        public TransitionEffect CurrentTransitionEffect
        {
            get; private set;
        }


        /// <summary>
        /// 设置过渡动画的持续时间
        /// </summary>
        public TimeSpan AnimationDuration
        {
            get { return (TimeSpan)GetValue(AnimationDurationProperty); }
            set { SetValue(AnimationDurationProperty, value); }
        }

        public static readonly DependencyProperty AnimationDurationProperty =
            DependencyProperty.Register("AnimationDuration", typeof(TimeSpan), typeof(TransitionEffectControl), new PropertyMetadata(TimeSpan.FromSeconds(0.6)));

        /// <summary>
        /// 设置在动画中控件是否可用(默认为false)
        /// </summary>
        public bool EnabledInAnimating { get; set; } = false;

        /// <summary>
        /// 指定动画的方向（默认为水平方向。仅对部分动画有效）
        /// </summary>
        public Orientation Orientation { get; set; } = Orientation.Horizontal;
        #endregion
    }


    /// <summary>
    /// 过度特效枚举
    /// </summary>
    public enum TransitionEffectType
    {
        /// <summary>
        /// 没有过渡效果
        /// </summary>
        None = -2,
        /// <summary>
        /// 随机
        /// </summary>
        Random = -1,

        BandedSwirl = 0,

        Blinds,
        /// <summary>
        /// 垮塌
        /// </summary>
        Blood,

        CircleReveal,
        /// <summary>
        /// 圆形挤压
        /// </summary>
        CirleStretch,

        CircularBlur,

        CloudReveal,

        Crumble,

        Disolve,

        Dropfade,

        Fade,

        LeastBright,
        /// <summary>
        /// 线性过渡
        /// </summary>
        LineReveal,

        MostBright,

        PixelateIn,

        PixelateOut,

        Pixelate,

        RadislBlur,

        RadialWiggle,
        /// <summary>
        /// 随机圆形过渡（圆的边缘不规则）
        /// </summary>
        RandomCircleReveal,
        /// <summary>
        /// 水波
        /// </summary>
        Ripple,

        RotateCrumble,

        Saturate,

        Shrink,
        /// <summary>
        /// 向左/上滑入
        /// </summary>
        SlideIn,
        /// <summary>
        /// 向右/向下划入
        /// </summary>
        SlideOut,

        SmoothSwirlGrid,

        SwirlGrid,

        Swirl,

        Water,

        Wave,
    }
}
